package com.oa.erp.ass.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mdp.core.err.BizException;
import com.mdp.core.service.BaseService;
import com.mdp.core.utils.BaseUtils;
import com.mdp.safe.client.entity.User;
import com.mdp.safe.client.utils.LoginUtils;
import com.oa.erp.ass.entity.AssetCard;
import com.oa.erp.ass.entity.AssetCardOper;
import com.oa.erp.ass.entity.AssetMaintenanceConsumables;
import com.oa.erp.ass.entity.AssetMng;
import com.oa.erp.ass.enums.AssetMngEnum;
import com.oa.erp.ass.enums.AssetStatusEnum;
import com.oa.erp.ass.enums.MngStatusEnum;
import com.oa.erp.ass.enums.TaskDetailEnum;
import com.oa.erp.ass.mapper.AssetMngMapper;
import com.oa.erp.ass.vo.AssetDetailVo;
import com.oa.erp.ass.vo.AssetMngVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author maimeng-mdp code-gen
 * @since 2023年10月8日
 */
@Service
public class AssetMngService extends BaseService<AssetMngMapper, AssetMng> {
    static Logger logger = LoggerFactory.getLogger(AssetMngService.class);

    /**
     * 自定义查询，支持多表关联
     *
     * @param page 分页条件
     * @param ew   一定要，并且必须加@Param("ew")注解
     * @param ext  如果xml中需要根据某些值进行特殊处理，可以通过这个进行传递，非必须，注解也可以不加
     * @return
     */
    public List<Map<String, Object>> selectListMapByWhere(IPage page, QueryWrapper ew, Map<String, Object> ext) {
        return baseMapper.selectListMapByWhere(page, ew, ext);
    }

    @Autowired
    private AssetCardOperService assetCardOperService;

    @Autowired
    private AssetMaintenanceConsumablesService assetMaintenanceConsumablesService;

    @Autowired
    private AssetCardService assetCardService;

    @Autowired
    private AssetInventoryTaskService assetInventoryTaskService;


    @Transactional
    public void insertAssetMsg(AssetMngVo assetMngVo) {
        User user = LoginUtils.getCurrentUserInfo();

        AssetMng assetMng = assetMngVo.getAssetMng();

        List<AssetDetailVo> detailVoList = assetMngVo.getAssetDetails();
        List<AssetMaintenanceConsumables> haocais = assetMngVo.getHaoCai();

        //1添加到主表
        this.insertAssetMsgMain(user, assetMng);

        //2.添加耗材->维修单
        assetMaintenanceConsumablesService.insertHaoCai(assetMng.getId(), haocais);

        //4.资产盘点->修改盘点任务关联资产的状态, 修改资产卡片的正在盘点状态.
        if (assetMng.getOpType().equals(AssetMngEnum.INVENTORY.getStatus())) {
            List<String> ids = new ArrayList<>();
            detailVoList.forEach(d -> ids.add(d.getCardId()));
            //更新资产卡片状态
            assetInventoryTaskService.updateCardInventoryStatus(ids, "0");
            //2.更新任务状态
            assetInventoryTaskService.updateTaskDetailStatus(ids, assetMng.getInventoryTask(), assetMng.getId(), TaskDetailEnum.INVENTORY_NORMAL.getStatus());
        }

        //5.资产盘亏->修改盘点任务关联资产的状态, 修改资产卡片的正在盘点状态.  //如果存在资产任务则是资产盘亏的处置单
        if (assetMng.getOpType().equals(AssetMngEnum.DISPOSE.getStatus()) && !StringUtils.isEmpty(assetMng.getInventoryTask())) {
            List<String> ids = new ArrayList<>();
            detailVoList.forEach(d -> ids.add(d.getCardId()));
            //更新资产卡片状态
            assetInventoryTaskService.updateCardInventoryStatus(ids, "0");
            //2.更新任务状态
            assetInventoryTaskService.updateTaskDetailStatus(ids, assetMng.getInventoryTask(), assetMng.getId(), TaskDetailEnum.INVENTORY_LOSSES.getStatus());
        }

        //3.添加资产操作信息记录资产更新状态
        assetCardOperService.insertDetailOper(detailVoList, getAssetStatus(assetMng.getOpType()), assetMng.getId());

        if (assetMng.getMngStatus().equals((MngStatusEnum.SUBMIT.getStatus()))) {
            //4.修改资产卡片当前最新状态
            assetCardService.updateCardStatus(detailVoList, getAssetStatus(assetMng.getOpType()));
        }

    }

    @Transactional
    public void updateAssetMsg(AssetMngVo assetMngVo) {
        //修改时时暂存为草稿，还是直接提交
        User user = LoginUtils.getCurrentUserInfo();
        AssetMng assetMng = assetMngVo.getAssetMng();
        List<AssetDetailVo> detailVoList = assetMngVo.getAssetDetails();
        List<AssetMaintenanceConsumables> haocais = assetMngVo.getHaoCai();

        //1.删除原本数据。
        this.deleteMngByPk(assetMng);

        //2添加到主表
        this.insertAssetMsgMain(user, assetMng);

        //3.添加耗材->维修单
        assetMaintenanceConsumablesService.insertHaoCai(assetMng.getId(), haocais);

        //4.添加资产操作信息记录资产更新状态
        assetCardOperService.insertDetailOper(detailVoList, getAssetStatus(assetMng.getOpType()), assetMng.getId());

        //5.资产盘点->修改盘点任务关联资产的状态, 修改资产卡片的正在盘点状态.
        if (assetMng.getOpType().equals(AssetMngEnum.INVENTORY.getStatus())) {
            List<String> ids = new ArrayList<>();
            detailVoList.forEach(d -> ids.add(d.getCardId()));
            //更新资产卡片状态
            assetInventoryTaskService.updateCardInventoryStatus(ids, "0");
            //2.更新任务状态和关联的操作记录Id
            assetInventoryTaskService.updateTaskDetailStatus(ids, assetMng.getInventoryTask(), assetMng.getId(), TaskDetailEnum.INVENTORY_NORMAL.getStatus());
        }

        //6.资产盘亏->修改盘点任务关联资产的状态, 修改资产卡片的正在盘点状态.  //如果存在资产任务则是资产盘亏的处置单
        if (assetMng.getOpType().equals(AssetMngEnum.DISPOSE.getStatus()) && !StringUtils.isEmpty(assetMng.getInventoryTask())) {
            List<String> ids = new ArrayList<>();
            detailVoList.forEach(d -> ids.add(d.getCardId()));
            //更新资产卡片状态
            assetInventoryTaskService.updateCardInventoryStatus(ids, "0");
            //2.更新任务状态
            assetInventoryTaskService.updateTaskDetailStatus(ids, assetMng.getInventoryTask(), assetMng.getId(), TaskDetailEnum.INVENTORY_LOSSES.getStatus());
        }

        if (assetMng.getMngStatus().equals((MngStatusEnum.SUBMIT.getStatus()))) {
            //5.修改资产卡片当前最新状态
            assetCardService.updateCardStatus(detailVoList, getAssetStatus(assetMng.getOpType()));
        }

    }

    /**
     * 添加资产维修单信息
     * @param assetMngVo
     */

    /**
     * 请在此类添加自定义函数
     */
    public void insertAssetMsgMain(User user, AssetMng assetMng) {
        assetMng.setReqBranchId(user.getBranchId());
        assetMng.setReqBranchName(user.getBranchName());
        this.insert(assetMng);
    }


    /**
     * 获取当前修改后的资产状态
     *
     * @param opType 操作类型
     * @return
     */
    private String getAssetStatus(String opType) {
        String status = AssetStatusEnum.LEAVEUNUSED.getStatus();
        AssetMngEnum dt = AssetMngEnum.getType(opType);
        switch (dt) {
            case USE:
                status = AssetStatusEnum.ISUSE.getStatus();
                break;
            case RETURN:
                status = AssetStatusEnum.LEAVEUNUSED.getStatus();
                break;
            case CHANGE:
                status = "change";
                break;
            case MAINT:
                status = AssetStatusEnum.MAINTAIN.getStatus();
                break;
            case LEASE:
                status = AssetStatusEnum.BORRON.getStatus();
                break;
            //调拨后的状态为在用
            case REALLOCATION:
                status = AssetStatusEnum.ISUSE.getStatus();
                break;
            //资产处置后的状态为报废
            case DISPOSE:
                status = AssetStatusEnum.SCRAP.getStatus();
                break;
            case INVENTORY:
                status = "inventory";
                break;
        }
        return status;
    }

    /**
     * 通过id获取单据明细
     *
     * @param assetMng
     * @return
     */
    public List<Map<String, Object>> getDetailById(IPage page, QueryWrapper ew, Map<String, Object> assetMng) {
//        List<Map<String, Object>> result = this.selectList("getDetailById", assetMng);
        return this.selectListMapByWhere(page, ew, assetMng);
    }


    /**
     * 删除单据通过主键
     *
     * @param assetMng
     */
    @Transactional
    public void deleteMngByPk(AssetMng assetMng) {

        //验证该数据是否可以删除
        this.isCanDeleteOrUpdateMng(assetMng.getId());

        //1.删除main表
        this.deleteByPk(assetMng);

        //2.删除操作表
        Map<String, Object> param = new HashMap<>();
        param.put("requireId", assetMng.getId());
//        assetCardOperService.deleteByWhere((AssetCardOper) param);
        assetCardOperService.deleteByWhere(BaseUtils.fromMap(param, AssetCardOper.class));
        //3.维修单删除耗材表
        if ((AssetMngEnum.MAINT.getStatus()).equals(assetMng.getOpType())) {
//            assetMaintenanceConsumablesService.deleteByWhere((AssetMaintenanceConsumables) param);
            assetMaintenanceConsumablesService.deleteByWhere(BaseUtils.fromMap(param, AssetMaintenanceConsumables.class));
        }

    }

    /**
     * 通过主键批量删除
     *
     * @param assetMngs
     */
    @Transactional
    public void BatchDeleteMngByPk(List<AssetMng> assetMngs) {
        //1.删除main表
        this.batchDelete(assetMngs);

        //2.删除操作表
        assetCardOperService.batchDeleteOperDetailByRequireId(assetMngs);

        //3.维修单删除耗材表
        if ((AssetMngEnum.MAINT.getStatus()).equals(assetMngs.get(0).getOpType())) {
            assetMaintenanceConsumablesService.batchDeleteMaintenanceByRequireId(assetMngs);
        }
    }

    public void isCanDeleteOrUpdateMng(String id) {
        AssetMng assetMng = this.selectOneObject(new AssetMng(id));

        if (StringUtils.isEmpty(assetMng)) {
            throw new BizException("该申请单不存在,不能进行该操作");
        }

        if (assetMng.getMngStatus().equals(MngStatusEnum.SUBMIT.getStatus())) {
            throw new BizException("该申请单已提交,不能进行该操作");
        }

    }


    @Transactional
    public void insertAssetMngOpr(AssetMngVo assetMngVo) {
        User user = LoginUtils.getCurrentUserInfo();

        AssetMng assetMng = assetMngVo.getAssetMng();

        List<AssetDetailVo> detailVoList = assetMngVo.getAssetDetails();

        //1添加到主表
        this.insertAssetMsgMain(user, assetMng);

        //2.添加资产操作信息记录资产更新状态
        assetCardOperService.insertDetailOper(detailVoList, getAssetStatus(assetMng.getOpType()), assetMng.getId());

    }

    @Transactional
    public void updateAssetMsgOpr(AssetMngVo assetMngVo) {
        User user = LoginUtils.getCurrentUserInfo();
        AssetMng assetMng = assetMngVo.getAssetMng();
        List<AssetDetailVo> detailVoList = assetMngVo.getAssetDetails();

        //1.删除原本数据。
        this.deleteMngByPk(assetMng);

        //2添加到主表
        this.insertAssetMsgMain(user, assetMng);

        //3.添加资产操作信息记录资产更新状态
        assetCardOperService.insertDetailOper(detailVoList, getAssetStatus(assetMng.getOpType()), assetMng.getId());
    }

    /**
     * 流程审批过程中回调该接口，更新业务数据
     * 如果发起流程时上送了restUrl，则无论流程中是否配置了监听器都会在流程发生以下事件时推送数据过来
     * eventName: PROCESS_STARTED 流程启动完成 全局
     * PROCESS_COMPLETED 流程正常结束 全局
     * PROCESS_CANCELLED 流程删除 全局
     * create 人工任务启动
     * complete 人工任务完成
     * assignment 人工任务分配给了具体的人
     * delete 人工任务被删除
     * TASK_COMPLETED_FORM_DATA_UPDATE 人工任务提交完成后，智能表单数据更新
     * <p>
     * 其中 create/complete/assignment/delete事件是需要在模型中人工节点上配置了委托代理表达式 ${taskBizCallListener}才会推送过来。
     * 在人工任务节点上配置 任务监听器  建议事件为 complete,其它assignment/create/complete/delete也可以，一般建议在complete,委托代理表达式 ${taskBizCallListener}
     *
     * @param flowVars {flowBranchId,agree,procInstId,startUserid,assignee,actId,taskName,mainTitle,branchId,bizKey,commentMsg,eventName,modelKey} 等
     * @return 如果tips.isOk==false，将影响流程提交
     **/
    //资产领用流程
    @Transactional
    public void processApprova(IPage page, QueryWrapper ew, Map<String, Object> flowVars) {
        String eventName = (String) flowVars.get("eventName");
        String agree = (String) flowVars.get("agree");
        String branchId = (String) flowVars.get("branchId");
        String assetMngId = (String) flowVars.get("assetMngId");//资产领用编号
        String bizKey = (String) flowVars.get("bizKey");
        if ("asset_receive_process_approva".equals(bizKey)) {
        } else {
            throw new BizException("不支持的业务,请上送业务编码【bizKey】参数");
        }

        if ("complete".equals(eventName)) {
            if ("1".equals(agree)) {
                this.updateFlowStateByAssetMngId(null, flowVars);
            } else {
                this.updateFlowStateByAssetMngId(null, flowVars);
            }
        } else {
            // PROCESS_COMPLETED->已领用
            if ("TASK_CREATED".equals(eventName)) {
                //资产管理员节点ID已写死为asset_keeper
                if ("asset_keeper".equals(flowVars.get("actId"))) {
                    //流程表和mng表更新为waiting,表示待领用
                    flowVars.put("mngStatus", "2");
                    this.updateFlowStateByAssetMngId("", flowVars);
                }
            } else {
                if ("PROCESS_STARTED".equals(eventName)) {
                    Map<String, Object> bizQuery = new HashMap<>();
                    bizQuery.put("id", assetMngId);
                    if (StringUtils.isEmpty(assetMngId)) {
                        throw new BizException("请上送资产领用单编号-assetMngId");
                    }
                    if (StringUtils.isEmpty(branchId)) {
                        throw new BizException("请上送branchId");
                    }
                    List<Map<String, Object>> bizList = this.selectListMapByWhere(page, ew, bizQuery);
                    if (bizList == null || bizList.size() == 0) {
                        throw new BizException("没有找到对应资产领用单,单号为【" + assetMngId + "】");
                    } else {
                        Map<String, Object> bizObject = bizList.get(0);
                        if ("1".equals(bizObject.get("bizFlowState"))) {
                            throw new BizException("该资产领用单正在审批中，不能再发起审批");
                        }
                    }
                    flowVars.put("assetMngId", assetMngId);
                    this.updateFlowStateByAssetMngId("1", flowVars);
                } else if ("PROCESS_COMPLETED".equals(eventName)) {
                    //流程表、mng表更新
                    flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                    if ("1".equals(agree)) {

                        //可用则更新资产状态
                        AssetCardOper assetCardOper = new AssetCardOper();
                        assetCardOper.setRequireId(assetMngId);
                        List<AssetCardOper> assetCardOpers = assetCardOperService.selectListByWhere(assetCardOper);
                        AssetMng aAssetMng = new AssetMng();
                        aAssetMng.setId(assetMngId);
                        aAssetMng = this.selectOneObject(aAssetMng);
                        for (AssetCardOper assetDetailVo : assetCardOpers) {
                            AssetCard assetCard = new AssetCard();
                            BeanUtils.copyProperties(assetDetailVo, assetCard);
                            assetCard.setBranchId(branchId);
                            assetCard.setLastEditUserid(aAssetMng.getReqUserid());
                            assetCard.setLastEditTime(new Date());
                            assetCard.setLastEditUsername(aAssetMng.getReqUsername());

                            //更新卡片最新的责任人，仓库地址，使用部门
                            assetCard.setDeptid(assetDetailVo.getNowDeptid());
                            assetCard.setDeptName(assetDetailVo.getNowDeptName());
                            assetCard.setStoreAddress(assetDetailVo.getNowStoreAddress());
                            assetCard.setWarehouseId(assetDetailVo.getNowWarehouseId());
                            assetCard.setWarehouseName(assetDetailVo.getNowWarehouseName());
                            assetCard.setPersonLiableUserid(assetDetailVo.getNowPsersonLiableUserid());
                            assetCard.setPersonLiableUsername(assetDetailVo.getNowPsersonLiableUsername());

                            assetCard.setCardStatus("1");
                            assetCardService.updateSomeFieldByPk(assetCard);
                        }

                        //更新AssetMng表和流程表状态
                        this.updateFlowStateByAssetMngId("2", flowVars);
                    } else {
                        this.updateFlowStateByAssetMngId("3", flowVars);
                    }
                } else if ("PROCESS_CANCELLED".equals(eventName)) {
                    //cancel为流程取消状态
                    //更新asset_mng状态，删除asset_card_opr
                    flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                    this.updateFlowStateByAssetMngId("4", flowVars);
                }
            }
        }
    }

    //资产归还流程
    @Transactional
    public void returnProcessApprova(IPage page, QueryWrapper ew, Map<String, Object> flowVars) {
        String eventName = (String) flowVars.get("eventName");
        String agree = (String) flowVars.get("agree");
        String branchId = (String) flowVars.get("branchId");
        String assetMngId = (String) flowVars.get("assetMngId");//资产归还编号
        String bizKey = (String) flowVars.get("bizKey");
        if ("asset_return_process_approva".equals(bizKey)) {
        } else {
            throw new BizException("不支持的业务,请上送业务编码【bizKey】参数");
        }

        if ("complete".equals(eventName)) {
            if ("1".equals(agree)) {
                this.updateFlowStateByAssetMngId(null, flowVars);
            } else {
                this.updateFlowStateByAssetMngId(null, flowVars);
            }
        } else {
            // PROCESS_COMPLETED->已归还
            if ("TASK_CREATED".equals(eventName)) {
                //
            } else {
                if ("PROCESS_STARTED".equals(eventName)) {
                    Map<String, Object> bizQuery = new HashMap<>();
                    bizQuery.put("id", assetMngId);
                    if (StringUtils.isEmpty(assetMngId)) {
                        throw new BizException("请上送资产归还单编号-assetMngId");
                    }
                    if (StringUtils.isEmpty(branchId)) {
                        throw new BizException("请上送branchId");
                    }
                    List<Map<String, Object>> bizList = this.selectListMapByWhere(page, ew, bizQuery);
                    if (bizList == null || bizList.size() == 0) {
                        throw new BizException("没有找到对应资产归还单,单号为【" + assetMngId + "】");
                    } else {
                        Map<String, Object> bizObject = bizList.get(0);
                        if ("1".equals(bizObject.get("bizFlowState"))) {
                            throw new BizException("该资产归还单正在审批中，不能再发起审批");
                        }
                    }
                    this.updateFlowStateByAssetMngId("1", flowVars);
                } else if ("PROCESS_COMPLETED".equals(eventName)) {
                    //流程表、mng表更新
                    flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                    if ("1".equals(agree)) {

                        //可归还则需要更新assetCard资产状态
                        AssetCardOper assetCardOper = new AssetCardOper();
                        assetCardOper.setRequireId(assetMngId);
                        List<AssetCardOper> assetCardOpers = assetCardOperService.selectListByWhere(assetCardOper);
                        List<AssetCard> assetCards2 = new ArrayList<>();
                        AssetMng aAssetMng = new AssetMng();
                        aAssetMng.setId(assetMngId);
                        aAssetMng = this.selectOneObject(aAssetMng);
                        for (AssetCardOper assetDetailVo : assetCardOpers) {
                            AssetCard assetCard = new AssetCard();
                            BeanUtils.copyProperties(assetDetailVo, assetCard);
                            assetCard.setBranchId(branchId);
                            assetCard.setLastEditUserid(aAssetMng.getReqUserid());
                            assetCard.setLastEditTime(new Date());
                            assetCard.setLastEditUsername(aAssetMng.getReqUsername());

                            //更新卡片仓库地址
                            assetCard.setStoreAddress(assetDetailVo.getNowStoreAddress());
                            assetCard.setWarehouseId(assetDetailVo.getNowWarehouseId());
                            assetCard.setWarehouseName(assetDetailVo.getNowWarehouseName());

                            assetCard.setCardStatus("0");
                            assetCardService.updateSomeFieldByPk(assetCard);
                        }
                        //更新AssetMng表和流程表状态
                        this.updateFlowStateByAssetMngId("2", flowVars);
                    } else {
                        //reject为未通过状态
                        this.updateFlowStateByAssetMngId("3", flowVars);
                    }
                } else if ("PROCESS_CANCELLED".equals(eventName)) {
                    //cancel为流程取消状态
                    flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                    this.updateFlowStateByAssetMngId("4", flowVars);
                }
            }
        }
    }

    /**
     * @param bizFlowState 0初始1审批中2审批通过3审批不通过4流程取消或者删除
     * @param flowVars
     */
    public void updateFlowStateByAssetMngId(String bizFlowState, Map<String, Object> flowVars) {
        flowVars.put("bizFlowState", bizFlowState);
        if (!"1".equals(bizFlowState)) {
            flowVars.put("bizProcInstId", flowVars.get("procInstId"));
        }
        baseMapper.updateFlowStateByAssetMngId(flowVars);

        this.assetCardOperService.updateFlowStateByAssetMngId(bizFlowState, flowVars);
    }
}

